#!/usr/bin/python
# -*- coding: utf-8 -*-
import re
import os
import sys


def fetch(url, outfile=None):
    """TODO: Error"""
    import urllib2
    # fetch html
    req = urllib2.Request(url)
    req.add_header('Accept-encoding', 'gzip')
    response = urllib2.urlopen(req)
    html = response.read()
    # uncompress gzip 
    if response.info().get('Content-Encoding') == 'gzip':
        from StringIO import StringIO
        import gzip
        data = StringIO(html)
        file = gzip.GzipFile(fileobj=data)
        html = file.read()
    # output to a file
    if outfile:
        with open(outfile, 'w') as f:
            f.write(html)
    return html


def whois(name, domain='.com'):
    """
    * http://whois.aliyun.com/whois/domain/52poke.com
    * https://pypi.python.org/pypi/python-whois/0.6.1
    """
    return 'no whois'


def domain(name, domain='.com'):
    """
    * http://panda.www.net.cn/cgi-bin/check.cgi?area_domain=52poke.com
    """
    if not name:
        return False, -1, 'no name'
    if not domain:
        return False, -2, 'no domain'
    # domain
    url = 'http://panda.www.net.cn/cgi-bin/check.cgi?area_domain=' + name + domain
    html = fetch(url)
    pattern = r'<original>\s*(\d*?)\s*:\s*(.*?)\s*</original>'
    m = re.search(pattern, html)
    if not m:
        return False, -3, 'no result'
    # 210 : Domain name is available                域名可用
    # 211 : In Use | unsupport tld type.            域名已用
    # 212 : Domain name is invalid                  域名无效
    # 213 : Timeout | Check domain is timed out     查询超时
    # ("||216|Query frequency is too high, please try again later")
    return True, int(m.group(1)), m.group(2)


# Colors


PRINT = lambda s: sys.stdout.write(s)
NEWLINE = lambda: PRINT(os.linesep)

CUU = lambda n=1: PRINT('\033[%dA' % n) # Cursor Up, 1: default
CPL = lambda n=1: PRINT('\033[%dF' % n) # Cursor Previous Line, 1: default
EL = lambda n=1: PRINT('\033[%dK' % n)  # Erase in Line, 1: from cursor to beginning

EUL = lambda n=1: PRINT('\033[%dA\033[K' % n)
EPL = lambda n=1: PRINT('\033[%dF\033[K' % n)

RESET = lambda: PRINT('\033[0m')

def COLOR(code, s=None, reset=True):
    color = '\033[%d;1m' % code
    if s:
        s = color + s
        if reset: s = s + '\033[0m'
        return s
    else:
        PRINT(color)
    if reset: RESET()

RED = lambda s=None, r=False: COLOR(31, s, r)
GREEN = lambda s=None, r=False: COLOR(32, s, r)
CYAN = lambda s=None, r=False: COLOR(36, s, r)
WHITE = lambda s=None, r=False: COLOR(37, s, r)

def pinfo(*args, **kwargs):
    if not args: return
    for arg in args:
        if not arg: continue
        if callable(arg): arg()
        else: PRINT(arg)
    if kwargs.get('reset', True): RESET()
    if kwargs.get('newline', True): NEWLINE()

def pstrong(*args, **kwargs):
    pinfo(GREEN, *args, **kwargs)

def pfile(file, *args, **kwargs):
    if not file: return
    if not args: return
    for arg in args:
        if not arg: continue
        if callable(arg): arg()
        else:
            PRINT(arg)
            file.write(arg)
    if kwargs.get('reset', True): RESET()
    if kwargs.get('newline', True): NEWLINE()
    file.write(os.linesep)


# Pokeman :)


def fetch_poke(outfile='poke.txt'):
    url = 'http://wiki.52poke.com/wiki/%E5%AE%9D%E5%8F%AF%E6%A2%A6%E5%88%97%E8%A1%A8%EF%BC%88%E6%8C%89%E5%85%A8%E5%9B%BD%E5%9B%BE%E9%89%B4%E7%BC%96%E5%8F%B7%EF%BC%89/%E7%AE%80%E5%8D%95%E7%89%88'
    fetch(url, outfile)


def parse_poke(infile='poke.txt', filter_func=None):
    with open(infile, 'r') as f:
        # parse table
        pattern_table = r'^<table class=".*?eplist.*?">.*?</table>'
        m = re.search(pattern_table, f.read(), re.DOTALL|re.MULTILINE)
        if not m: return
        table = m.group(0)
        # parse texts in each row
        pattern_tr = r'^<tr>.*?<td>(.*?)</td>.*?<td>(.*?)</td>.*?<td>(.*?)</td>.*?<td>(.*?)</td>.*?</tr>'
        pattern_a = r'<a.*?>\s*(.*?)\s*</a>'
        for m in re.finditer(pattern_tr, table, re.DOTALL|re.MULTILINE):
            texts = []
            for d in m.groups():
                r = re.search(pattern_a, d)
                text = r.group(1) if r else d.strip()
                texts.append(text)
            if filter_func and filter_func(texts):
                continue
            yield tuple(texts)


def domain_poke(domain='.com', len_max=5):
    temp = 'poke.txt'
    result = 'poke_result' + domain

    if os.path.isfile(temp):
        pstrong('Poke html already existed in %s' % temp)
    else:
        pstrong('Fetching poke html ...')
        fetch_poke(temp)
        pstrong('Saved poke html into %s' % temp)

    pstrong('Parsing the pokedex items ...')
    items = parse_poke(temp, lambda item: len(item[3]) > len_max)

    pstrong('Writing to file: ', RED, result)

    with open(result, 'w') as f:
        from functools import partial
        pfile = partial(globals()['pfile'], f)

        pfile(GREEN, 'Domain name: ', RED, domain)
        pfile(GREEN, 'Pokemon name: ', RED, ('<=%d' % len_max))

        g_domain = globals()['domain']
        format_info = '{0} {1:>%d}' % (len_max + len(domain))
        n = 0
        total = 0
        prunning = lambda pre=None: pinfo(pre, GREEN, 'Running: ', RED, '%d/%d' % (n, total))
        prunning()
        for item in items:
            total += 1
            prunning(EPL)
            name = item[3]
            ok, code, msg = g_domain(name, domain)
            if code == 210:
                n += 1
                infos = [format_info.format(len(name), name.lower() + domain)]
                if len(name) < len_max:
                    infos.insert(0, RED)
                    infos.append(RESET)
                infos.append(', ' + ' '.join(item))
                pfile(EPL, *infos)
                prunning()
        pfile(EPL, GREEN, 'Found ', RED, '%d/%d' % (n, total), GREEN, ' pokedex items')


# Alphabet :)


def domain_alphabet(domain='.com', size=4):
    import string
    import itertools

    result = 'alphabet_result' + domain

    def alphabet():
        for l in string.ascii_lowercase:
            yield l

    with open(result, 'w') as f:
        from functools import partial
        pfile = partial(globals()['pfile'], f)

        total = str(26**size)

        pfile(GREEN, 'Domain name: ', RED, domain)
        pfile(GREEN, 'Letters\' number: ', RED, str(size))
        pfile(GREEN, 'Total: ', RED, total)

        g_domain = globals()['domain']
        format_info = '{0:>0%d} {1:>%d}' % (len(total), size + len(domain))
        n = 0
        total = 0
        prunning = lambda pre=None: pinfo(pre, GREEN, 'Running: ', RED, '%d/%d' % (n, total))
        prunning()
        for letters in itertools.product(alphabet(), repeat=size):
            total += 1
            prunning(EPL)
            name = ''.join(letters)
            ok, code, msg = g_domain(name, domain)
            if code == 210:
                n += 1
                info = format_info.format(n, name + domain)
                pfile(EPL, info)
                prunning()
        pfile(EPL, GREEN, 'Found ', RED, '%d/%d' % (n, total), GREEN, ' items')


if __name__ == '__main__':
    domain_poke('.cc')
    # domain_alphabet('.cn')
